import { Application } from "mydog";
import { cmd } from "../../../config/cmd";
import { doudizhu_msg } from "../../../config/proto/doudizhu";
import { DEF } from "../../definition/consts";
import { Dictionary, IUidSid } from "../../definition/interface";
import { GameLogic } from "../gameLogic";
import { PokerSet } from "../poker/set";
import { GAME_TYPE, GetGameName, IAnalyzer, IRecorder, ISetChecker } from "../pokergame/factory";
import { SetInfo } from "../pokergame/setInfo";
import { CARD, dizhuScoreArray, GameState, ICard, ICardGroup, IGamePlayer, IPlayer, IRole, QiangdizhuState, Timer } from "./definition";

class LastCardsType {
  public PlayerIndex: number;              // 出牌的玩家index
  public Cards: PokerSet;                  // 出的牌
  public PlayerCardIndexs: Array<number>;  // 扑克牌在出牌玩家所有牌中的index
  public PokerSetTypeInfo: SetInfo;        //

  constructor(playerIndex: number, cards: PokerSet, cardIndexs: Array<number>, setTypeInfo: SetInfo) {
    this.PlayerIndex = playerIndex;
    this.Cards = cards;
    this.PlayerCardIndexs = cardIndexs;
    this.PokerSetTypeInfo = setTypeInfo;
  }
}

export class DoudizhuGame extends GameLogic {

  private _name: string;                          // 游戏名称

  /*
  private baseScore: number;                      // 底分
  private currMulti: number;                      // 当前倍率
  private CalledLoardNum: number;                 // 叫过地主的人数
  private lordIndex: number;                      // 地主索引
  private CurrPlayerIndex: number;                // 当前叫地主或者出牌人的index
  private FirstCallScoreIndex: number;            // 第一个叫地主的人的index
  private OutCardIndexs: number[];                // 出完牌的用户index

  private pokerCards: PokerSet;                   // 当前游戏中的所有的牌
  private lastCards: LastCardsType;               // 最后的出牌结构

  private Players: Array<IPlayer>;                // 玩家数组
  private playerCards: Array<PokerSet>;           // 同桌不同玩家的牌的切片
  private setChecker: ISetChecker;                //
  private playerPokerRecorders: Array<IRecorder>; // 玩家的记牌器数组
  private playerPokerAnalyzer: Array<IAnalyzer>;  // 玩家的牌型分析器
  private playerCardRecorder: Array<IRecorder>;   // 每个玩家的记牌器, 帮助玩家记录其他两家手里牌的合计情况
  private bottomCards: PokerSet;                  // 底牌
  */


  private _state: number;             // 游戏状态

  private _bottomCards: Array<ICard>; // 底牌
  private _dizhuSeat: number;         // 地主座位
  private _dizhuMaxScore;             // 抢地主时，出的最高分

  private _firstPaySeat: number;      // 首先抢地主的座位

  private _nowTurnSeat: number;       // 当前出牌玩家座位
  private _nowTurnTimer: number;      // 当前倒计时

  private _lastPlaySeat: number;      // 上个出牌玩家座位
  private _lastCardGroup: ICardGroup; // 上个打出的牌组

  private _playerMap: Dictionary<IGamePlayer> = {};
  private _cards: Array<ICard> = null as any;

  constructor(app: Application, roomId: number, uidsid: Array<IUidSid>) {
    super(app, roomId, uidsid);

    this._name = GetGameName(GAME_TYPE.LANDLORD);











    this._state = GameState.qiangdizhu;

    this._bottomCards = null as any;
    this._dizhuSeat = 0;
    this._dizhuMaxScore = 0;

    this._firstPaySeat = 0;

    this._nowTurnSeat = 0;
    this._nowTurnTimer = 0;

    this._lastPlaySeat = DEF.USER.ID_INVALID;
    this._lastCardGroup = null as any;

    this.initGame();
  }

  // 初始化玩家
  private initPlayer() {
    for (let i = 0; i < this.users.length; i++) {
      this._playerMap[i] = { uid: this.users[i].uid, sid: this.users[i].sid, seat: i, role: IRole.Peasant, score: QiangdizhuState.none, record: null as any, cards: null as any }
    }
  }

  // 查询战绩
  private async checkRecord() {
    for (let i = 0; i < this.users.length; i++) {
      this._playerMap[i].record = await this.app.rpcAwait(DEF.SEVER.ID.DATABASE).database.main.getDoudizhuInfo(this._playerMap[i].uid) as any;
    }
  }

  // 新建牌组
  private newCards() {
    if (!!this._cards) {
      return this._cards;
    }

    this._cards = new Array<ICard>();
    let id = 0;
    for (let i = 3; i <= 14; i++) {
      this._cards.push({ id: id++, color: CARD.COLOR.spade, score: i });
      this._cards.push({ id: id++, color: CARD.COLOR.heart, score: i });
      this._cards.push({ id: id++, color: CARD.COLOR.club, score: i });
      this._cards.push({ id: id++, color: CARD.COLOR.diamond, score: i });
    }
    this._cards.push({ id: id++, color: CARD.COLOR.spade, score: CARD.SCORE.two });
    this._cards.push({ id: id++, color: CARD.COLOR.heart, score: CARD.SCORE.two });
    this._cards.push({ id: id++, color: CARD.COLOR.club, score: CARD.SCORE.two });
    this._cards.push({ id: id++, color: CARD.COLOR.diamond, score: CARD.SCORE.two });
    this._cards.push({ id: id++, color: CARD.COLOR.spade, score: CARD.SCORE.joker_black });
    this._cards.push({ id: id++, color: CARD.COLOR.heart, score: CARD.SCORE.joker_red });
    return this._cards;
  }

  // 洗牌
  private shuffleCards() {
    let i = this._cards.length;
    while (!!i) {
      const j = Math.floor(Math.random() * i--);
      [this._cards[j], this._cards[i]] = [this._cards[i], this._cards[j]];
    }
    return this._cards;
  }

  // 发牌
  private dealCards() {
    for (let i = 0; i < this.users.length; i++) {
      const playerCards = this._cards.slice(17 * i, 17 * (i + 1) + 1);
      playerCards.sort((a, b) => a.score < b.score ? 1 : -1); // 从大到小
      this._playerMap[i].cards = playerCards;
    }
    this._bottomCards = this._cards.slice(17 * 3, this._cards.length);
  }

  // 只会在所有玩家准备后执行一次
  private initGame() {
    this.initPlayer();
    this.checkRecord();
    this.newCards();
    this._firstPaySeat = Math.floor(Math.random() * this.users.length);
    this._state = GameState.jiaodizhu;

    // send initInfo
    const res: doudizhu_msg.s2c_onGameInit = new doudizhu_msg.s2c_onGameInit();
    res.state = this._state;
    res.players = this.getAllPlayersWithoutCards();
    this.sendMessageToAll(cmd.doudizhu_onGameInit, res);

    // res.nowTurnSeat = this._nowTurnSeat;
    // res.nowTurnTimer = this._nowTurnTimer;
    // res.dizhuSeat = this._dizhuSeat;
    // res.dizhuScore = this._dizhuMaxScore;
    // res.lastPlaySeat = this._lastPlaySeat;
  }

  public onStart() {
    this.shuffleCards();
    this.dealCards();
    this._state = GameState.qiangdizhu;
    this._nowTurnSeat = this.firstPaySeat();
    this._nowTurnTimer = Timer.qiangdizhu;

    // send startInfo
    const res: doudizhu_msg.s2c_onGameStart = new doudizhu_msg.s2c_onGameStart();
    res.state = this._state;
    res.turnSeat = this._nowTurnSeat;
    res.turnTimer = this._nowTurnTimer;

    const players = this.getAllPlayers();
    for (let i = 0; i < players.length; i++) {
      res.cards = players[i].cards;
      this.sendMessageToSeat(cmd.doudizhu_onGameStart, players[i].seat, res);
    }
  }

  public onEnd() { }

  public onQiangdizhu(uid: number, score: number) {
    if (this._state !== GameState.qiangdizhu) { return; }

    const player = this.getPlayerByUid(uid);
    if (!!player) {
      if (player.seat !== this._nowTurnSeat) { return; }
      if (dizhuScoreArray.indexOf(score) === -1) { return; }
      if (score !== 0 && score <= this._dizhuMaxScore) { return; }

      this._dizhuMaxScore = score;
      const res: doudizhu_msg.s2c_onQiangdizhu = new doudizhu_msg.s2c_onQiangdizhu();

      // 叫3分直接为地主
      if (score === 3) {
        this.determineDizhu(player);

        res.seat = player.seat;
        res.score = score;
        this.sendMessageToAll(cmd.doudizhu_onQiangdizhu, res);
        return;
      }

      const nextSeat = this.nextSeat(player.seat);
      const nextPlayer = this._playerMap[nextSeat];
      if (nextPlayer.score === -1) {
        this._nowTurnSeat = nextSeat;
        this._nowTurnTimer = Timer.play;

        res.seat = -1;
        res.score = score;
        this.sendMessageToAll(cmd.doudizhu_onQiangdizhu, res);
        return;
      }

      // 都不抢，第一个人为地主
      if (this._dizhuMaxScore <= 0) {
        const playerOne = this._playerMap[0];
        this.determineDizhu(playerOne);

        res.seat = this._dizhuSeat;
        res.score = score;
        this.sendMessageToAll(cmd.doudizhu_onQiangdizhu, res);
        return;
      }



    }
  }

  private determineDizhu(player: IGamePlayer) {
    this._state = GameState.play;
    this._dizhuSeat = player.seat;
    this._nowTurnSeat = player.seat;
    this._nowTurnTimer = Timer.play;
    this._lastPlaySeat = player.seat;
    player.cards.push(...this._bottomCards);
    player.cards.sort((a, b) => { return a.score < b.score ? 1 : -1; });
  }

  private firstPaySeat() {
    if (this._firstPaySeat > 2) { this._firstPaySeat = 0; }
    return this._firstPaySeat++;
  }

  private nextSeat(seat: number) {
    seat++;
    if (seat > 2) { seat = 0; }
    return seat;
  }

  // player
  private getAllPlayers() {
    const players = [];
    for (let key in this._playerMap) {
      players.push(this._playerMap[key]);
    }
    return players;
  }

  private getAllPlayersWithoutCards() {
    const players = this.getAllPlayers();
    let newPlayers = [];
    for (let i = 0; i < players.length; i++) {
      const player = players[i];
      newPlayers.push({ uid: player.uid, seat: player.seat });
    }
    return newPlayers;
  }

  private getPlayerByUid(uid: number) {
    for (let key in this._playerMap) {
      if (this._playerMap[key].uid === uid) {
        return this._playerMap[key];
      }
    }
    return null;
  }

  private getPlayerBySeat(seat: number) {
    return this._playerMap[seat];
  }

  private getAllPlayersUidsid() {
    // let uidsid = [];
    // for (let key in this._playerMap) {
    //   uidsid.push({ uid: this._playerMap[key], sid: this._playerMap[key].sid });
    // }
    // return uidsid;
    return this.users;
  }

  private getAllPlayersUidsidExceptUid(uid: number) {
    let uidsid = [];
    for (let key in this._playerMap) {
      if (this._playerMap[key].uid !== uid) {
        uidsid.push({ uid: this._playerMap[key].uid, sid: this._playerMap[key].sid });
      }
    }
    return uidsid;
  }

  private getAllPlayersUidsidExceptSeat(seat: number) {
    let uidsid = [];
    for (let key in this._playerMap) {
      if (key !== seat.toString()) {
        uidsid.push({ uid: this._playerMap[key].uid, sid: this._playerMap[key].sid });
      }
    }
    return uidsid;
  }

  // message
  public sendMessageToUid(route: number, uid: number, msg: any) {
    const player = this.getPlayerByUid(uid);
    if (!!player) {
      this.app.sendMsgByUidSid(route, msg, [{ uid: player.uid, sid: player.sid }]);
    }
  }

  public sendMessageToSeat(route: number, seat: number, msg: any) {
    const player = this._playerMap[seat];
    if (!!player) {
      this.app.sendMsgByUidSid(route, msg, [{ uid: player.uid, sid: player.sid }]);
    }
  }

  public sendMessageToAll(route: number, msg: any) {
    const uidsid = this.getAllPlayersUidsid();
    this.app.sendMsgByUidSid(route, msg, uidsid);
  }

  public sendMessageToAllExceptUid(route: number, uid: number, msg: any) {
    const uidsid = this.getAllPlayersUidsidExceptUid(uid);
    this.app.sendMsgByUidSid(route, msg, uidsid);
  }

  public sendMessageToAllExceptSeat(route: number, seat: number, msg: any) {
    const uidsid = this.getAllPlayersUidsidExceptSeat(seat);
    this.app.sendMsgByUidSid(route, msg, uidsid);
  }
}
